<?php

abstract class E_Entity
{	
	
	private $_key = '';
	public $_row = array();
	public $_updatestack = array();
	public $_isinsert = false;
	public $deletestack = 0;
	public function __construct()
	{	
		
		$zend_config = Zend_Registry::get("zend_config");
		if($zend_config->cache->sql->isopen == "open")
		{
			if(!Zend_Registry::isRegistered('sqlcache'))
			{
				$applicationRoot = Zend_Registry::get("applicationRoot");
				$cachepath = $zend_config->cache->sql->path;
				$cacheFile = $applicationRoot.'/'.$cachepath;
				$frontendOptions = array(
				    'lifeTime' => 7200, // 两小时的缓存生命期
				    'automatic_serialization' => true
				);
				  
				$backendOptions = array(
				    'cache_dir' => $cacheFile,
					'hashed_directory_level'=>2 // 放缓存文件的目录
				);  
				// 取得一个Zend_Cache_Core 对象
				$cache = Zend_Cache::factory('Core','File',$frontendOptions,$backendOptions);
				Zend_Registry::set('sqlcache', $cache);
			}
		}
	}
	public function getDbHandle()
	{
		$_DB = E_DBConnectionPool::getDbHandle();
		return $_DB;
	}
	public function setEntityKey($k, $v)
	{
		$this->_key =  $v.'_'.$this->table[$k].'_'.get_class($this);
		return $this->_key;
	}
	public function getEntityKey()
	{
		return $this->_key;
	}
    public function factoryEntity($sql, $bind = array())
	{
		$bind = addslashes_array($bind);
		$row = $this->getDbHandle()->fetch($sql,$bind);
		
		if(empty($row)) {return null;}
		
		$this->setEntityKey('id', $row[$this->table['id']]);
		$work = E_UnitOfWork::getWork();
		if($work->hasEntity($this->getEntityKey()))
		{
			 	$entity = $work->getEntity($this->getEntityKey());
			 	
			 	return $entity;
		}
		else
		{
			 //小心被覆盖
				if(!empty($row))
				{
					foreach($row as $k =>$v)
					{
						$dvalue[$k] = $v;
					}
				}
				else
				{
					$dvalue = $row;
				}
				$this->_row = $dvalue;
				unset($dvalue);
				$work->register($this);
			
		}
		return $this;
	}
	
	public function getEntityByIndexKey($sql, $id = '',$bind = array())
	{
		$bind = addslashes_array($bind);
		if(!empty($id))
		{
			
				$work = E_UnitOfWork::getWork();
				if($work->hasEntity($this->setEntityKey('id', $id)))
				{
					
					 	$entity = $work->getEntity($this->getEntityKey());
					 	return $entity;
				}
				else 
				{
					return $this->factoryEntity($sql,$bind);
				}
			
		}
		else 
		{
			return  $this->factoryEntity($sql,$bind);
		}
	}
	public  function birthEntity($sql,$bind = array())
	{
		$bind = addslashes_array($bind);
		$row = $this->getDbHandle()->fetchAll($sql,$bind);
		if(empty($row)) return array();
		$work = E_UnitOfWork::getWork();
		$EntityName = get_class($this);
		foreach($row as $value)
		{
			$entity = new  $EntityName();
			$entity->setEntityKey('id', $value[$this->table['id']]);
			if($work->hasEntity($entity->getEntityKey()))
			{
				$entity = $work->getEntity($entity->getEntityKey());
			}
			else
			{
				if(!empty($value))
				{
					foreach($value as $k =>$v)
					{
						$dvalue[$k] = $v;
					}
				}
				else
				{
					$dvalue = $value;
				}
				$entity->_row = $dvalue; 
				unset($dvalue);
				$work->register($entity);
			}
			
			//小心被覆盖
			$entitys[] = $entity;
		}
		return $entitys;
	}
	public function getId()
	{
		return $this->id;
	}
	public function __get($name)
	{
		
		if(!empty($this->table[$name]))
		{
			if(empty($this->_row[$this->table[$name]]))
			{
				$sql = "select {$this->table[$name]} from {$this->getTableName()} where {$this->table['id']} = {$this->_row[$this->table['id']]}";
				$row = $this->getDbHandle()->fetch($sql);
				$this->_row[$this->table[$name]] = $row[$this->table[$name]];
				return htmlspecialchars($row[$this->table[$name]],ENT_NOQUOTES );
			}
			else
			{	
				return htmlspecialchars($this->_row[$this->table[$name]],ENT_NOQUOTES );
			}
		}
		else
		{
			$map = $this->getJoinMap();
			if(array_key_exists($name , $map))
			{
				$entity = $map[$name]['Entity'];
				$method = $map[$name]['Method'];
				$param = $map[$name]['param'];
				$E = new $entity();
				$EE = $E->$method($this->$param);
				if($EE == NULL)
				{
					return new E_Nentity("");
				}
				return $EE;
			}
			
			
		}
		return '';
	}
	public function __set($name, $value)
	{	
		if(!empty($this->table[$name]))
		{
			$this->_row[$this->table[$name]] = $value;
			if(!$this->_isinsert)
			{
				$this->_updatestack[$this->table[$name]] = $value;
				$this->_updatestack[$this->table['version']] = $this->_row[$this->table['version']]+1;
				$this->_row[$this->table['version']] = $this->_row[$this->table['version']]+1;
				$this->_row[$this->table['mtime']] = $this->_updatestack[$this->table['mtime']] = time();
			}
			
		}
	}

	public function createEntityForRow($row)
	{
		$id = E_DBConnectionPool::getIDGeneratorByDb("IDGenerator")->getNextID();
		foreach($row as $k  => $v)
		{
			$row[$k] = $v;
		}
		$time = time();
		$row['id'] = $id;
		$row['version'] = 1;
		$row['ctime'] = $time;
		$row['mtime'] = $time;
		$this->_isinsert = true;
        $this->_row = $row;
        $this->setEntityKey('id', $row[$this->table['id']]);
		$work = E_UnitOfWork::getWork();
        $work->register($this);
        return $this;
	}

	public function getInsertSql()
	{
		if($this->_isinsert)
		{
			foreach ($this->_row as $col => $val)
		    {
		        $set[] = "`{$this->table[$col]}`";
		        $vals[] = "'".addslashes($val)."'";
		    }
		    $sql = "INSERT INTO "
	             . $this->getTableName()
	             . ' (' . implode(', ', $set).') '
	             . 'VALUES (' . implode(', ', $vals).')';
	   
	        return $sql;
		}
      
	}
	public function getUpdateSql()
	{
		if(!empty($this->_updatestack))
		{
			$where = $this->table['id']." ='".$this->_row["{$this->table['id']}"]."' and ";
			$version  = $this->_row["{$this->table['version']}"]+1;
			$where .= $this->table['version']." <'".$version."'";
			
			$set = array();
			
		    foreach ($this->_updatestack as $col => $val)
		    {
		        $set[] = "$col = '".addslashes($val)."'";
		        unset($set[$col]);
		    }
		    $sql = "UPDATE "
	             . $this->getTableName()
	             . ' SET ' . implode(',', $set)
	             . (($where) ? " WHERE $where" : '');
	         return $sql;
		}
	}
	public function isDelete()
	{
		if($this->deletestack)
			return true;
		else
			return false;		
	}
	public function delete()
	{
		$this->deletestack = 1;
	}
	public function getDeleteSql()
	{
		if($this->deletestack)
		{
			$where = $this->table['id']." ='".$this->_row["{$this->table['id']}"]."'";
			$sql = "delete from {$this->getTableName()}  where $where"; 
			return $sql;
		}
	}
	public static function page($request,$response, $param, $where, $class, $link = '',$params=array())
	{
		if(empty($where))
		{
			$where = " 1=1 ";
		}
		$page = $request->get('page');
		T_Page::$current_page_s = $page;
		if(empty($link))
		{
			T_Page::$subpage_link_s = array('module'=>$request->getModule(),
										'action'=>$request->getAction(),
										'method'=>$request->getMethod(),
										'query'=>$param,
										'param' =>$params
								  );
		}
		else
		{
			$link['query'] = $param;
			T_Page::$subpage_link_s = $link;
		}
		T_Page::$response_s = $response;
		T_Page::$nums_s = self::getPagenum($where, $class);
		T_Page::getPageController();
		$start = T_Page::$startPage_s;
		$len = T_Page::$each_disNums_s;
		return "limit $start, $len";
	}
	public static function getPagenum($where = " 1=1 ", $class)
	{	
		$entity = new $class(); //5.3 get_call_class;
		$DB = $entity->getDbHandle();
		$sql =  "select count(1) as num  from {$entity->getTableName()} where $where  and  status=1 $order";
		$row =  $DB->fetch($sql);
		return $row['num'];
	}
	public function __toString()
	{
		return $this->id;
	}
}    
?>